#ifndef X2B_H
#define X2B_H

#include "common.h"

template <AllegroVersion version>
struct x2B
{
    uint32_t t;
    uint32_t k;
    uint32_t footprint_string_ref;
    
    uint32_t un1; // Always null?
    
    int32_t coords[4];
    
    // Points to another x2B object? Just the next item, not interesting.
    uint32_t next;
    
    // Points to placed symbol (x2D)
    uint32_t ptr2;
    
    // Points to pad of some type (x0D)?
    uint32_t ptr3;
    
    // Symbol pad (x32)
    uint32_t ptr4;
    
    // x14?
    uint32_t ptr5;
    
    // Usually (but not always) points to footprint file path.
    uint32_t str_ptr;
    
    // x0E
    uint32_t ptr6;
    
    // x24
    uint32_t ptr7;
    
    // x28
    uint32_t ptr8;
    
    // 17.x?
    
    uint32_t TAIL;
    operator x2B<A_174>() const;
    static constexpr AllegroVersion versions[2] = {A_164, A_172};
};

#if __cplusplus >= 202002L
template <AllegroVersion version> requires(version >= A_164)
struct x2B<version>
{
    uint32_t t;
    uint32_t k;
    uint32_t footprint_string_ref;

    uint32_t un1; // Always null?

    int32_t coords[4];

    // Points to another x2B object? Just the next item, not interesting.
    uint32_t next;

    // Points to placed symbol (x2D)
    uint32_t ptr2;

    // Points to pad of some type (x0D)?
    uint32_t ptr3;

    // Symbol pad (x32)
    uint32_t ptr4;

    // x14?
    uint32_t ptr5;

    // Usually (but not always) points to footprint file path.
    uint32_t str_ptr;

    // x0E
    uint32_t ptr6;

    // x24
    uint32_t ptr7;

    // x28
    uint32_t ptr8;

    uint32_t un2; // Always null?

    // 17.x?
    COND_FIELD(version >= A_172, uint32_t, un3);

    uint32_t TAIL;
    operator x2B<A_174>() const;
    static constexpr AllegroVersion versions[2] = {A_164, A_172};
};
#else
template <> struct x2B<A_164>
{
    uint32_t t;
    uint32_t k;
    uint32_t footprint_string_ref;

    uint32_t un1; // Always null?

    int32_t coords[4];

    // Points to another x2B object? Just the next item, not interesting.
    uint32_t next;

    // Points to placed symbol (x2D)
    uint32_t ptr2;

    // Points to pad of some type (x0D)?
    uint32_t ptr3;

    // Symbol pad (x32)
    uint32_t ptr4;

    // x14?
    uint32_t ptr5;

    // Usually (but not always) points to footprint file path.
    uint32_t str_ptr;

    // x0E
    uint32_t ptr6;

    // x24
    uint32_t ptr7;

    // x28
    uint32_t ptr8;

    uint32_t un2; // Always null?

    uint32_t TAIL;
    operator x2B<A_174>() const;
    static constexpr AllegroVersion versions[2] = {A_164, A_172};
};
template<> struct x2B<A_165> : x2B<A_164> {};
template<> struct x2B<A_166> : x2B<A_164> {};

template <> struct x2B<A_172>
{
    uint32_t t;
    uint32_t k;
    uint32_t footprint_string_ref;

    uint32_t un1; // Always null?

    int32_t coords[4];

    // Points to another x2B object? Just the next item, not interesting.
    uint32_t next;

    // Points to placed symbol (x2D)
    uint32_t ptr2;

    // Points to pad of some type (x0D)?
    uint32_t ptr3;

    // Symbol pad (x32)
    uint32_t ptr4;

    // x14?
    uint32_t ptr5;

    // Usually (but not always) points to footprint file path.
    uint32_t str_ptr;

    // x0E
    uint32_t ptr6;

    // x24
    uint32_t ptr7;

    // x28
    uint32_t ptr8;

    uint32_t un2; // Always null?

    // 17.x?
    uint32_t un3;

    uint32_t TAIL;
    operator x2B<A_174>() const;
    static constexpr AllegroVersion versions[2] = {A_164, A_172};
};
template<> struct x2B<A_174> : x2B<A_172> {};
#endif

#endif // X2B_H
